The Invocation APIChapter 5The Invocation API allows software vendors to load the Java VM into an arbitrary native application. Vendors can deliver Java-enabled applications without having to link with the Java VM source code. This chapter begins with an overview of the Invocation API. This is followed by reference pages for all Invocation API functions. To enhance the embeddability of the Java VM, the Invocation API is extended in JDK 1.1.2 in a few minor ways. OverviewThe following code example illustrates how to use
functions in the Invocation API. In this example, the C++ code
creates a Java VM and invokes a static method, called #include <jni.h> /* where everything is defined */ ... JavaVM *jvm; /* denotes a Java VM */ JNIEnv *env; /* pointer to native method interface */ JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */ vm_args.version = 0x00010001; /* New in 1.1.2: VM version */ /* Get the default initialization arguments and set the class * path */ JNI_GetDefaultJavaVMInitArgs(&vm_args); vm_args.classpath = ...; /* load and initialize a Java VM, return a JNI interface * pointer in env */ JNI_CreateJavaVM(&jvm, &env, &vm_args); /* invoke the Main.test method using the JNI */ jclass cls = env->FindClass("Main"); jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V"); env->CallStaticVoidMethod(cls, mid, 100); /* We are done. */ jvm->DestroyJavaVM(); This example uses three functions in the API. The Invocation API allows a native application to use the JNI interface pointer to access VM features. The design is similar to Netscape’s JRI Embedding Interface. Creating the VMThe Attaching to the VMThe JNI interface pointer ( The attached thread should have enough stack space
to perform a reaonable amount of work. The allocation of stack
space per thread is operating system-specific. For example, using
pthreads, the stack size can be specified in the Unloading the VMThe main thread cannot detach itself from the VM.
Instead, it must call The VM waits until the main thread is the only
user thread before it actually unloads. User threads include both
Java threads and attached native threads. This restriction exists
because a Java thread or attached native thread may be holding
system resources, such as locks, windows, and so on. The
Initialization StructuresDifferent Java VM implementation will likely require different initialization arguments. It is difficult to come up with a standard initialization structure suitable for all present and future Java VMs. As a compromise, we reserve the first field (version) to identify the content of the initialization structure. Native applications embedding JDK 1.1.2 must set the version field to 0x00010001. VM implementations are encouraged to use the same initialization structure as JDK, although other implementations may choose to ignore some of the initialization arguments supported by JDK. Version numbers 0x80000000 to 0xFFFFFFFF are reserved, and should not be recognized by any VM implementation. The following code shows the structure used to initialize the Java VM in JDK 1.1.2. typedef struct JDK1_1InitArgs { /* The first two fields were reserved in JDK 1.1, and formally introduced in JDK 1.1.2. */ /* Java VM version */ jint version; /* System properties. */ char **properties; /* whether to check the Java source files are newer than * compiled class files. */ jint checkSource; /* maximum native stack size of Java-created threads. */ jint nativeStackSize; /* maximum Java stack size. */ jint javaStackSize; /* initial heap size. */ jint minHeapSize; /* maximum heap size. */ jint maxHeapSize; /* controls whether Java byte code should be verified: * 0 -- none, 1 -- remotely loaded code, 2 -- all code. */ jint verifyMode; /* the local directory path for class loading. */ const char *classpath; /* a hook for a function that redirects all VM messages. */ jint (*vfprintf)(FILE *fp, const char *format, va_list args); /* a VM exit hook. */ void (*exit)(jint code); /* a VM abort hook. */ void (*abort)(); /* whether to enable class GC. */ jint enableClassGC; /* whether GC messages will appear. */ jint enableVerboseGC; /* whether asynchronous GC is allowed. */ jint disableAsyncGC; /* Three reserved fields. */ jint reserved0; jint reserved1; jint reserved2; } JDK1_1InitArgs; In JDK 1.1.2, the initialization structure provides hooks so that a native application can redirect VM messages and obtain control when the VM terminates. The structure below is passed as an argument when
a native thread attaches to a Java VM in JDK 1.1.2. In actuality,
no arguments are required for a native thread to attach to the JDK
1.1.2. The typedef struct JDK1_1AttachArgs { /* * JDK 1.1 does not need any arguments to attach a * native thread. The padding is here to satisfy the C * compiler which does not permit empty structures. */ void *__padding; } JDK1_1AttachArgs; Library and Version ManagementIn JDK 1.1, once a native library is loaded, it is visible from all class loaders. Therefore two classes in different class loaders may link with the same native method. This leads to two problems:
In the Java 2 SDK, each class loader manages its own set of
native libraries. The same JNI native library cannot be
loaded into more than one class loader. Doing so causes
To facilitate versioning control and resource management, JNI libraries in the Java 2 Platform may optionally export the following two functions: JNI_OnLoad
JNI_OnLoad when the native library is
loaded (for example, through System.loadLibrary ).
JNI_OnLoad must return the JNI version needed by the
native library.
In order to use any of the new JNI functions, a native library
must export a LINKAGE:Exported from native libraries that contain native method implementation. SINCE SDK/JRE 1.4:In order to use the JNI functions introduced in J2SE release
1.2, in addition to those that were available in JDK 1.1, a native
library must export a In order to use the JNI functions introduced in J2SE release
1.4, in addition to those that were available in release 1.2, a
native library must export a If the native library does not export a JNI_OnUnload
JNI_OnUnload when the class loader
containing the native library is garbage collected. This function
can be used to perform cleanup operations. Because this function is
called in an unknown context (such as from a finalizer), the
programmer should be conservative on using Java VM services, and
refrain from arbitrary Java call-backs.
Note that LINKAGE:Exported from native libraries that contain native method implementation.Invocation API FunctionsThe typedef const struct JNIInvokeInterface *JavaVM; const struct JNIInvokeInterface ... = { NULL, NULL, NULL, DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, GetEnv, AttachCurrentThreadAsDaemon }; Note that three Invocation API functions,
JNI_GetDefaultJavaVMInitArgs
Returns a default configuration for the Java VM. Before calling this function, native code must1 set the vm_args->version field to the JNI version it expects the VM to support. In JDK 1.1.2, vm_args->version must be set to 0x00010001. After this function returns, vm_args->version will be set to the actual JNI version the VM supports. LINKAGE:Exported from the native library that implements the Java virtual machine. PARAMETERS:
RETURNS:Returns “0” if the requested version is supported; returns a negative number if the requested version is not supported. JNI_GetCreatedJavaVMs
Returns all Java VMs that have been created. Pointers to VMs are written in the buffer vmBuf in the order they are created. At most bufLen number of entries will be written. The total number of created VMs is returned in *nVMs. JDK 1.1.2 does not support creating more than one VM in a single process. LINKAGE:Exported from the native library that implements the Java virtual machine. PARAMETERS:
RETURNS:Returns “0” on success; returns a negative number on failure. JNI_CreateJavaVM
Loads and initializes a Java VM. The current
thread becomes the main thread. Sets the JDK 1.1 does not support creating more than one VM in a single process. The version field in vm_args must2 be set to 0x00010001. In JDK 1.1, the second argument to In the Java 2 SDK, we introduce a standard VM initialization
structure. Backward compatibility is preserved. If the VM
initialization argument points to a typedef struct JavaVMInitArgs { jint version; jint nOptions; JavaVMOption *options; jboolean ignoreUnrecognized; } JavaVMInitArgs; The typedef struct JavaVMOption { char *optionString; void *extraInfo; } JavaVMOption; The size of the array is denoted by the nOptions field in
In addition, each VM implementation may support its own set of
non-standard option strings. Non-standard option names must begin
with " Here is the example code that creates a Java VM in the Java 2 SDK: JavaVMInitArgs vm_args; JavaVMOption options[4]; options[0].optionString = "-Djava.compiler=NONE"; /* disable JIT */ options[1].optionString = "-Djava.class.path=c:\myclasses"; /* user classes */ options[2].optionString = "-Djava.library.path=c:\mylibs"; /* set native library path */ options[3].optionString = "-verbose:jni"; /* print JNI-related messages */ vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = 4; vm_args.ignoreUnrecognized = TRUE; /* Note that in the Java 2 SDK, there is no longer any need to call * JNI_GetDefaultJavaVMInitArgs. */ res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); if (res < 0) ... The Java 2 SDK still supports LINKAGE:Exported from the native library that implements the Java virtual machine. PARAMETERS:
RETURNS:Returns “0” on success; returns a negative number on failure. DestroyJavaVM
Unloads a Java VM and reclaims its resources. Only the main thread can unload the VM. The system waits until the main thread is only remaining user thread before it destroys the VM. The support for LINKAGE:Index 3 in the JavaVM interface function table. PARAMETERS:
RETURNS:Returns “0” on success; returns a negative number on failure. JDK 1.1.2 does not support unloading the VM. AttachCurrentThread
Attaches the current thread to a Java VM. Returns
a JNI interface pointer in the Trying to attach a thread that is already attached is a no-op. A native thread cannot be attached simultaneously to two Java VMs. When a thread is attached to the VM, the context class loader is the bootstrap loader. LINKAGE:Index 4 in the JavaVM interface function table. PARAMETERS:
In JDK 1.1, the second argument to
In the Java 2 SDK, you pass typedef struct JavaVMAttachArgs { jint version; /* must be JNI_VERSION_1_2 */ char *name; /* the name of the thread, or NULL */ jobject group; /* global ref of a ThreadGroup object, or NULL */ } JavaVMAttachArgs RETURNS:Returns “0” on success; returns a negative number on failure. AttachCurrentThreadAsDaemonjint AttachCurrentThreadAsDaemon(JavaVM* vm, void** penv, void* args); Same semantics as AttachCurrentThread, but the newly-created java.lang.Thread instance is a daemon. If the thread has already been attached via either AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine simply sets the value pointed to by penv to the JNIEnv of the current thread. In this case neither AttachCurrentThread nor this routine have any effect on the daemon status of the thread. LINKAGE:Index 7 in the JavaVM interface function table.
vm: the virtual machine instance to which the current thread will be attached. penv: a pointer to the location in which the JNIEnv interface pointer for the current thread will be placed. args: a pointer to a JavaVMAttachArgs structure.
Returns zero on success; otherwise, returns a negative number.
None. SINCE:SDK/JRE 1.4 DetachCurrentThread
Detaches the current thread from a Java VM. All Java monitors held by this thread are released. All Java threads waiting for this thread to die are notified. In JDK 1.1, the main thread cannot be detached
from the VM. It must call In the Java 2 SDK, the main thread can be detached from the VM. The main thread, which is the thread that created
the Java VM, cannot be detached from the VM. Instead, the main
thread must call LINKAGE:Index 5 in the JavaVM interface function table. PARAMETERS:
RETURNS:Returns “0” on success; returns a negative number on failure. GetEnv
LINKAGE:Index 6 in the JavaVM interface function table. RETURNS:If the current thread is not attached to the VM, sets
PARAMETERS:
1. JDK 1.1 did not require the native code to set the version field. For backward compatibility, JDK 1.1.2 assumes that the requested version is 0x00010001 if the version field is not set. Future versions of JDK will require the version field to be set to an appropriate value. 2. See footnote 1.
|